package com.ericsson.common.util;

import com.ericsson.common.pojo.InputStreamChannelExec;
import com.jcraft.enipjsch.*;;

import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;


public class EnipSshUtil {
    private String host = null;
    private String user = null;
    private String password = null;
    private Session session = null;
    private Logger log;

    public EnipSshUtil(String host, String user, String password) {
        this.host = host;
        this.user = user;
        this.password = password;
    }

    public EnipSshUtil(String host, String user, String password, Logger log) {
        this.host = host;
        this.user = user;
        this.password = password;
        this.log = log;
    }

    public void connect() throws JSchException {
        Session openSession = null;
        JSch jsch = new JSch();
        openSession = jsch.getSession(user, host, 22);
        openSession.setPassword(password);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        openSession.setConfig(config);
        openSession.connect();
        this.session = openSession;
        System.out.println("ssh2 create connect success...");
    }
    public String execCommand(String command) {
        String result = "";
        ChannelExec openChannel = null;
        String charset = "UTF-8";
        try {
            if (session == null) {
                connect();
            }
            openChannel = (ChannelExec) session.openChannel("exec");
            openChannel.setCommand(command);
            openChannel.setErrStream(System.err);
            //openChannel.setPty(false);
            openChannel.setPtyType("vt102");
            openChannel.connect();
            InputStream in = openChannel.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName(charset)));
            String buf = null;
            while ((buf = reader.readLine()) != null) {
                result += buf + System.getProperty("line.separator");
            }

        } catch (Exception e) {
            result += e.getMessage();
        } finally {
            if (openChannel != null && !openChannel.isClosed()) {
                openChannel.disconnect();
            }
        }
        return result;
    }

    public Map<String, Set<String>> execCommandMap(String command) {
        Map<String, Set<String>> resulyMap=new HashMap<>();
        ChannelExec openChannel = null;
        String charset = "UTF-8";
        try {
            if (session == null) {
                connect();
            }
            openChannel = (ChannelExec) session.openChannel("exec");
            openChannel.setCommand(command);
            openChannel.setErrStream(System.err);
            openChannel.setPtyType("vt102");
            openChannel.connect();
            InputStream in = openChannel.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName(charset)));
            String buf = null;
            while ((buf = reader.readLine()) != null) {
                if(!"".equals(buf)) {
                    String []temp=buf.split(",");
                    if(temp.length==2&&resulyMap.containsKey(temp[1])){
                        resulyMap.get(temp[1]).add(temp[0]);
                    }else{
                        Set<String> tempList=new HashSet<>();
                        tempList.add(temp[0]);
                        resulyMap.put(temp[1],tempList);
                    }
                }
            }

        } catch (Exception e) {
        } finally {
            if (openChannel != null && !openChannel.isClosed()) {
                openChannel.disconnect();
            }
        }
        return resulyMap;
    }

    public void disconnect() {
        if (session != null && session.isConnected()) {
            session.disconnect();
            System.out.println("ssh2 session disconnect success...");
        }
    }

    public String sendCommand(String cmd, String end) throws Exception {

        PrintWriter printWriter = new PrintWriter(out);
        printWriter.println(cmd);
        printWriter.flush();
        return readUntil(end);
    }

    public String sendCommand(String cmd, String end,int count) throws Exception {
        PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(out,"UTF-8"));
        printWriter.println(cmd);
        printWriter.flush();
        Thread.currentThread().sleep(2000l);
        return readUntil(end,count);
    }

    public String sendCommandV2(String cmd, String end,int count) throws Exception {
        System.out.println(cmd);
        out.write((cmd+" \n\r").getBytes("UTF-8"));
        out.flush();
        Thread.currentThread().sleep(2000l);
        return readUntil(end,count);
    }

    public String sendCommandV3(String cmd, String end) throws Exception {
        System.out.println(cmd);
        out.write((cmd+" \n\r").getBytes("UTF-8"));
        out.flush();
        Thread.currentThread().sleep(2000l);
        return readUntilV3(end,log);
    }

    public String sendCommandV4(String cmd, String end,int count) throws Exception {
        System.out.println(cmd);
        out.write((cmd+"\n\r").getBytes("UTF-8"));
        out.flush();
        Thread.currentThread().sleep(2000l);
        return readUntil(end,count);
    }

    public String sendCommandV5(String cmd) throws Exception {
        System.out.println(cmd);
        out.write((cmd+" \n\r").getBytes("UTF-8"));
        out.flush();
        Thread.currentThread().sleep(2000l);
        return readUntilV5();
    }

    public String sendCommandV6(String cmd) throws Exception {
        System.out.println(cmd);
        out.write((cmd+" \n\r").getBytes("UTF-8"));
        out.flush();
        Thread.currentThread().sleep(2000l);
        return readUntilV6();
    }



    private ChannelShell channel = null;
    OutputStream out = null;
    InputStream in =null;
    public ChannelShell getShellChannel() throws Exception{
        channel = (ChannelShell) session.openChannel("shell");
        //channel.setPty(false);
        //channel.setPtyType("dumb");
        channel.setPtyType("dumb");
        channel.connect(30*1000);
        out = channel.getOutputStream();
        in = channel.getInputStream();
        return channel;
    }

    public String readUntil(String pattern) {
        try {
            char lastChar = pattern.charAt(pattern.length() - 1);
            StringBuffer sb = new StringBuffer();
            char ch = (char) in.read();
            while (true) {
                sb.append(ch);
                if (ch == lastChar) {
                    if (sb.toString().endsWith(pattern)) {
                        return sb.toString();
                    }
                }
                ch = (char) in.read();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String readUntil(String pattern,int count) throws Exception {
        int i =0;
        char lastChar = pattern.charAt(pattern.length() - 1);
        StringBuffer sb = new StringBuffer();
        BufferedReader reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));
        char ch = (char) reader.read();
        while (true) {
            sb.append(ch);
            //System.out.print(ch);
            if (ch == lastChar) {
                i++;
                if (i==count && sb.toString().endsWith(pattern)) {
                    //System.out.println("");
                   //System.out.println("========= sb:"+sb);
                    return sb.toString();
                }
            }
            ch = (char) reader.read();
        }
    }

    public String readUntilV3(String pattern,Logger log) throws Exception {
        StringBuffer sb = new StringBuffer();
        BufferedReader reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));
        String line = null;
        String result = null;
        int i = 0;
        while(true){
            line = reader.readLine();
            i++;
            if(i%10000==0){
                log.info(" ======= count:"+i);
            }
            //System.out.println("line:"+line+" len:"+line.length());
            result = result + line + "\r\n";
            if(line!=null&&line.contains(pattern)){
                log.info(" ======= result success:"+i);
                System.out.println("result success");
                reader.close();
                return result;
            }
            if(i>=100000){
                reader.close();
                return result;
            }
        }
    }

    public String readUntilV5() throws Exception {
        boolean flag1 = false,flag2 = false;
        StringBuffer sb = new StringBuffer();
        BufferedReader reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));
        char ch = (char) reader.read();
        int ich;
        while (true) {
            sb.append(ch);
            ich = (int)ch;
            if(ich==32&&flag1==false){
                flag1 = true;
                ch = (char) reader.read();
                continue;
            }
            if(ich==13&&flag2==false&&flag1==true){
                flag2 = true;
                ch = (char) reader.read();
                continue;
            }else if(ich==10&&flag1==true&&flag2==true){
                System.out.println("result success V5");
                return sb.toString();
            }else{
                flag1 = false;
                flag2 = false;
            }
            ch = (char) reader.read();
        }
    }

    public String readUntilV6() throws Exception {
        BufferedReader reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));
        String line = null;
        String result = null;
        int i = 0;
        while((line = reader.readLine())!=null){
            i++;
            System.out.println("line:"+line+" len:"+line.length()+"  i:"+i);
            result = result + line + "\r\n";
            /*if(line.contains(pattern)){
                System.out.println("result success");
                return result;
            }*/
        }
        return result;
    }

    public String readUntilv2(String pattern,int count) throws Exception {
        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0)
                    break;
               // System.out.println(new String(tmp, 0, i));
            }
        }

    }
    private void transToSSH(Channel channel, String command) throws IOException {
        if (channel != null) {
            OutputStream outputStream = channel.getOutputStream();
            outputStream.write(command.getBytes());
            outputStream.flush();
        }
    }

    public InputStreamChannelExec execCommandReturnStream(String command) {
        InputStreamChannelExec Isce = new InputStreamChannelExec();
        String charset = "UTF-8";
        ChannelExec openChannel = null;
        InputStreamReader is = null;
        try {
            if (session == null) {
                // 重新连接一次
                connect();
            }
            openChannel = (ChannelExec) session.openChannel("exec");
            openChannel.setCommand(command);
            openChannel.setErrStream(System.err);
            openChannel.connect();
            InputStream in = openChannel.getInputStream();
            is = new InputStreamReader(in, Charset.forName(charset));
        } catch (Exception e) {
            e.getMessage();
        } finally {
            Isce.setIs(is);
            Isce.setEnipCe(openChannel);
            if (openChannel != null && !openChannel.isClosed()) {
                openChannel.disconnect();
            }
        }
        return Isce;
    }

    public String sendCommands(String[] cmds) throws Exception {
        for(String cmd :cmds) {
            System.out.println(cmd);
            if(cmds[0].equals(cmd)){
                TimeUnit.MILLISECONDS.sleep(20000);
            }else{
                TimeUnit.MILLISECONDS.sleep(5000);
            }
            out.write((cmd + "\r\n").getBytes("UTF-8"));
            out.flush();
        }
        return readUtil();
    }


    public String readUtil() throws Exception {
        byte[] tmp=new byte[8192];
        StringBuilder sb = new StringBuilder();
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;

                String s = new String(tmp, 0, i);
                if (s.indexOf("--More--") >= 0 ) {
                    out.write((" ").getBytes());
                    out.flush();
                }
                sb.append(new String(tmp, 0, i));
                //System.out.print(s);
            }

            if(channel.isClosed()){
                if(in.available()>0) continue;
                System.out.println("exit-status: "+channel.getExitStatus());
                break;
            }
            TimeUnit.MILLISECONDS.sleep(400);
            //System.out.println("=========="+in.available());
        }
        return sb.toString();
    }




    public static void main(String args[]) throws Exception {

       /* SSHUtil sshUtil=new SSHUtil("192.168.1.230","root","1qaz#EDC");
        sshUtil.connect();
        ChannelShell cs=sshUtil.getShellChannel();
        sshUtil.readUntil("#");
        sshUtil.transToSSH(cs,"pwd");
        sshUtil.readUntil("#");*/

        /*SSHUtil ssh = new SSHUtil("192.168.1.230", "root", "1qaz#EDC");
        ssh.connect();
        try {
            ssh.getShellChannel();
            //ssh.sendCommand("terminal length 0","#");
            String a = ssh.sendCommandV2("ssh ericsson@192.168.1.230", ":",1);
            System.out.println("========"+a);
            //String ab = ssh.sendCommandV3("1qaz#EDC", "~>");
            String ab = ssh.sendCommandV4("1qaz#EDC",">",1);
            System.out.println("========"+ab);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ssh.disconnect();*/
    }
}
